#pragma once

#include <chrono>
#include <ctime> // for std::clock()

#define MEASURE_CPU_TIME(description, epochs, loop_body) \
    do { \
        std::clock_t total_start = std::clock(); \
        for (int64_t i = 0; i < epochs; i++) { \
            loop_body \
        } \
        std::clock_t total_end = std::clock(); \
        double total_cpu_time = ((double)(total_end - total_start)) / CLOCKS_PER_SEC; \
        double avg_time = total_cpu_time / epochs; \
        \
        const char* time_unit = "s"; \
        double display_time = avg_time; \
        \
        if (avg_time < 1e-6) { \
            time_unit = "ns"; \
            display_time = avg_time * 1e9; \
        } else if (avg_time < 1e-3) { \
            time_unit = "us"; \
            display_time = avg_time * 1e6; \
        } else if (avg_time < 1.0) { \
            time_unit = "ms"; \
            display_time = avg_time * 1e3; \
        } \
        \
        LogInfo() << description << " Summary: Total CPU time: " << total_cpu_time << " s" \
                  << ", Epochs: " << epochs \
                  << ", Avg time per execution: " << display_time << " " << time_unit \
                  << ", Executions per second: " << (1.0 / avg_time); \
    } while(0)

#define MEASURE_EXECUTION_TIME(description, epochs, loop_body) \
    do { \
        auto start = std::chrono::high_resolution_clock::now(); \
        for(int64_t i = 0; i < epochs; i++) { \
            loop_body \
        } \
        auto end = std::chrono::high_resolution_clock::now(); \
        auto duration = end - start; \
        double total_time_ns = std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count(); \
        double avg_time_ns = total_time_ns / epochs; \
        \
        /* 自动选择合适的时间单位 */ \
        const char* unit = "ns"; \
        double display_time = avg_time_ns; \
        \
        if (avg_time_ns >= 1e9) { \
            unit = "s"; \
            display_time = avg_time_ns / 1e9; \
        } else if (avg_time_ns >= 1e6) { \
            unit = "ms"; \
            display_time = avg_time_ns / 1e6; \
        } else if (avg_time_ns >= 1e3) { \
            unit = "us"; \
            display_time = avg_time_ns / 1e3; \
        } \
        \
        /* 计算每秒执行次数 */ \
        double exec_per_sec = 1e9 / avg_time_ns; \
        \
        LogInfo() << description << " Performance:" \
                  << "\n  Total time: " << (total_time_ns / 1e9) << " s" \
                  << "\n  Epochs: " << epochs \
                  << "\n  Avg time per execution: " << display_time << " " << unit \
                  << "\n  Executions per second: " << exec_per_sec; \
    } while(0)
